from .form import ArticleModelForm
from .models import Article, Category, Tag

import markdown
import re
from markdown.extensions.toc import TocExtension

from django.shortcuts import render, HttpResponse, redirect, reverse,get_object_or_404  # 请求成功返回，错误返回404
from django.contrib.auth.decorators import login_required
# from django_comments.models import Comment
from django.http import Http404
from django.contrib import messages
from django.db.models import Q
from django.utils.text import slugify
from django.views import View
from django.views.generic import ListView,DetailView
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
from pure_pagination import PaginationMixin


# @login_required(login_url="/myaccount/login/")
class ArticleAdd(View):
    """
    添加文章
    """

    def get(self, request):
        form = ArticleModelForm()
        print(request.user)
        print(type(request.user))
        if type(request.user) == "<class 'django.utils.functional.SimpleLazyObject'>":
            return redirect(reverse("myaccount:login"))
        if request.user == 'AnonymousUser':
            return redirect(reverse("myaccount:login"))
        return render(request, "article/add.html", {"form": form})

    def post(self, request):
        form = ArticleModelForm(request.POST)
        print(request.POST)
        if form.is_valid():
            print(form.cleaned_data)
            print("error:", form.errors)
            new_article = form.save(commit=False)  # commit=False暂时不提交到数据库
            new_article.author = request.user  # 保存作者为当前用户

            new_article.save()

            form.save_m2m()  # 保存 tags 的多对多关系
            return redirect(reverse('index'))
        return HttpResponse("error")


class ArticleDetail(DetailView):
    model = Article
    template_name = 'article/detail.html'
    context_object_name = 'articles_list'

    def get(self,request, *args, **kwargs):
        # 覆写 get 方法的目的是因为每当文章被访问一次，就得将文章阅读量 +1
        # get 方法返回的是一个 HttpResponse 实例
        # 之所以需要先调用父类的 get 方法，是因为只有当 get 方法被调用后，
        # 才有 self.object 属性，其值为 Post 模型实例，即被访问的文章 post

        response = super(ArticleDetail, self).get(request, *args, **kwargs)

        # 将文章阅读量 +1
        # 注意 self.object 的值就是被访问的文章 post
        self.object.increase_views()

        # 视图必须返回一个 HttpResponse 对象
        return response

    def get_object(self, queryset=None):
        # 覆写 get_object 方法的目的是因为需要对 post 的 body 值进行渲染
        article = super().get_object(queryset=None)
        md = markdown.Markdown(extensions=[
            'markdown.extensions.extra',
            # 'markdown.extensions.codehilite',
            'markdown.extensions.fenced_code',
            TocExtension(slugify=slugify),
        ])
        article.body = md.convert(article.body)

        m = re.search(r'<div class="toc">\s*<ul>(.*)</ul>\s*</div>', md.toc, re.S)
        article.toc = m.group(1) if m is not None else ''

        return article

def article_detail(request, pk):
    """
    文章详情
    :param request:
    :param id: 文章ID
    :return:
    """


    article = get_object_or_404(Article, pk=pk)


    md = markdown.Markdown(extensions=[
        'markdown.extensions.extra',
        # 'markdown.extensions.codehilite',
        'markdown.extensions.fenced_code',
        # 'markdown.extensions.toc',
        TocExtension(slugify=slugify),
    ])

    article.body = md.convert(article.body)

    print("md.tco:",md.toc)

    # 在models.py中处理了空目录,由于在models中处理了空目录，这里就不做处理
    # m = re.search(r'<div class="toc">\s*<ul>(.*)</ul>\s*</div>', md.toc, re.S)  # 处理空目录
    # article.toc = m.group(1) if m is not None else ''


    #   浏览量
    article.increase_views()
    # article.counter += 1
    # article.save(update_fields=['counter'])
    article.toc = md.toc
    print("article.toc:---",article.toc)

    return render(request, "article/detail.html", {"article": article})


class IndexView(PaginationMixin,ListView):
    """
    model.将 model 指定为 Post，告诉 django 我要获取的模型是 Post。
    template_name。指定这个视图渲染的模板。
    context_object_name。指定获取的模型列表数据保存的变量名，这个变量会被传递给模板。
    """
    model = Article
    template_name = 'framework/index.html'
    context_object_name = 'article_list'
    # 指定 paginate_by 属性后开启分页功能，其值代表每一页包含多少篇文章
    paginate_by = 5


def article_list(request):
    """
    文章列表
    :param request:
    :return:
    """

    search = request.GET.get('search')
    print("search:--", search)

    if search:
        articles = Article.objects.filter(Q(body__icontains=search) | Q(title__icontains=search))
        search = ''
    elif search == '':
        articles = Article.objects.all().order_by('-created_time')  # 按发布文章时间排序

    paginator = Paginator(articles,5)
    current_page = request.GET.get("page")

    try:
        article_list = paginator.page(current_page)
    except PageNotAnInteger:
        article_list = paginator.page(1)
    except EmptyPage:
        # 如果超过最大页数，显示最后一页
        article_list = paginator.page(paginator.num_pages)


    return render(request, 'framework/index.html', {"article_list": article_list})


@login_required(login_url="/myaccount/login/")
def article_edit(request, id):
    """
    编辑文章
    :param request:
    :param id:
    :return:
    """
    article = Article.objects.get(pk=id)
    if article.author != request.user:
        return HttpResponse("无权修改!")
    if request.method == 'POST':
        edit_form = ArticleModelForm(request.POST, instance=article)
        if edit_form.is_valid():
            print(edit_form.cleaned_data)
            edit_form.save()
            return redirect(reverse('article:article_list'))
            # return redirect(reverse('article:article_list',kwargs={"id":id}))
    else:
        edit_form = ArticleModelForm(instance=article)

        return render(request, 'article/edit.html', {"edit_form": edit_form})


'''

class Article_Create(View):
    """
    新建文章
    """
    def get(self,request):
        form = ArticleModelForm()
        print("form-------",form)
        return render(request,'article/article_create.html',{"form":form})

    def post(self,request):
        form = ArticleModelForm(request.POST)
        print(form)
        if form.is_valid():
            print(form.cleaned_data)

            new_form = form.save(commit=False)  # commit=False暂时不提交到数据库
            new_form.author = request.user  # 保存作者为当前用户
            new_form.save()
            form.save_m2m() # 保存多对多关系


            return HttpResponse('ok')
        print(form.errors)
        return HttpResponse('error')
'''


@login_required(login_url="/myaccount/login/")
def article_delete(request, id):
    """
    安全删除文章
    :param request:
    :param id:  文章的id
    :return:
    """
    if request.method == 'POST':
        print(request.POST)
        article = Article.objects.filter(pk=id).delete()
        return redirect(reverse('index'))
    else:
        return HttpResponse("只允许使用post方式")


def search(request):
    """
    搜索
    """
    try:
        data = {}
        wd = request.GET.get('q')
        if not wd:
            error_msg = "请输入搜索关键词"
            messages.add_message(request, messages.ERROR, error_msg, extra_tags='danger')
            return redirect('blog:index')

        article_list = Article.objects.filter(Q(title__icontains=wd) | Q(body__icontains=wd))
    except Exception:
        raise Http404

    paginator = Paginator(article_list,5)
    current_page = request.GET.get("page")

    try:
        article_list = paginator.page(current_page)
    except PageNotAnInteger:
        article_list = paginator.page(1)
    except EmptyPage:
        # 如果超过最大页数，显示最后一页
        article_list = paginator.page(paginator.num_pages)


    return render(request, "framework/index.html", {"article_list": article_list})

class ArchiveView(ListView):
    model = Article
    template_name = 'framework/index.html'
    context_object_name = 'archives_list'


def archive(request, year, month):
    """
    文章归档
    """
    archives_list = Article.objects.filter(created_time__year=year,
                                       created_time__month=month
                                       ).order_by('-created_time')
    return render(request, 'framework/index.html', context={'archives_list': archives_list})


class CategoryView(IndexView):
    """
    CategoryView 类中指定的属性值和 IndexView 中是一模一样的,直接继承IndexView
    """

    def get_queryset(self):
        """
        获取指定分类下的文章列表数据
        """
        cate = get_object_or_404(Category, pk=self.kwargs.get('pk'))
        return super(CategoryView, self).get_queryset().filter(category=cate)


def category(request, pk):
    # 记得在开始部分导入 Category 类
    cate = get_object_or_404(Category, pk=pk)
    post_list = Article.objects.filter(category=cate).order_by('-created_time')
    return render(request, 'framework/index.html', context={'post_list': post_list})


class TagView(ListView):
    model = Tag
    template_name = 'framework/index.html'
    context_object_name = 'tags_list'


def tag(request, pk):
    # 记得在开始部分导入 Tag 类
    t = get_object_or_404(Tag, pk=pk)
    tags_list = Article.objects.filter(tags=t).order_by('-created_time')
    return render(request, 'framework/index.html', context={'tags_list': tags_list})


